内存限制
Node 基于 V8 构建,所以存在一定的内存限制(64 位系统下约为 1.4GB, 32 位系统下约为 0.7GB)
可用 process.memoryUsage()
查看
在启动 node 时可以通过传递--max-old-space-size
或 --max-new-space-size
更改,前者对应单位 MB,用于更改老生代内存,后者对应单位 KB,用于更改新生代内存
V8 的垃圾回收机制
V8 中内存分为新生代(存活时间较短的对象)和老生代(存活时间较长的对象)
新生代
Scavenge 算法(主要采用了 Cheney 算法)
- 将堆内存一分为二,每一部分空间叫 semispace,使用中的叫 From,闲置的叫 To
- 开始垃圾回收时,先检查 From 中的存活,将其复制到 To,其余释放,完成后 From 与 To 二者交换(这个交换的过程也称翻转)
- 是一种典型的牺牲空间换取时间的算法,但是非常适合新生代这种场合
老生代
晋升
若一个对象经过多次复制依然存活时,会被移动到老生代中,称为晋升
晋升的要求:(将对象从 From 到 To 时):
- 若对象经历过一次 Scavenge 回收,则复制到老生代空间里
- 若 To 中空间使用大于 25%,则复制到老生代空间里
算法
老生代垃圾回收的算法:
- mark-sweep 算法:字面上理解,第一步,标记;第二步,清除。标记活着的对象,只清理死亡的对象。缺点,会存在碎片空间。
- mark-compact 算法:第一步,标记死亡对象;第二步,整理,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。
主要使用 mark-sweep:因为速度快
全停顿(stop-the-world)
在进行垃圾回收的时候会全停顿,而在老生代中全停顿时间很久,所以有增量标记
无法立即回收的内存
- 全局变量
- 闭包
堆外内存
Node 中的内存使用并非都是通过 V8 进行分配的,不是通过 V8 分配的内存称为堆外内存
- Buffer 使用的是堆外内存,没有堆内存的大小限制